﻿#if MONO_CECIL
#else
#define _NET_REFLECTOR
#endif

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using CallGraphExtractor.CecilAdapter;
using Reflector;
using Reflector.CodeModel;

namespace CallGraphExtractor
{
    public class Extractor
    {
        #region Fields

        private BackgroundWorker mExtractionWorker;
        private BackgroundWorker mGetMembersWorker;
        private BackgroundWorker mGetTypesWorker;
        private BackgroundWorker mGetNamespacesWorker;
        private BackgroundWorker mGetModulesWorker;
        private BackgroundWorker mGetAssembliesWorker;

        private AutoResetEvent mOnGetAssembliesDoneBlocker = new AutoResetEvent(false);
        private AutoResetEvent mOnGetModulesDoneBlocker = new AutoResetEvent(false);
        private AutoResetEvent mOnGetTypesDoneBlocker = new AutoResetEvent(false);
        private AutoResetEvent mOnGetMembersDoneBlocker = new AutoResetEvent(false);
        private AutoResetEvent mOnGetNamespacesDoneBlocker = new AutoResetEvent(false);
        private AutoResetEvent mOnExtractionDoneBlocker = new AutoResetEvent(false);

        #endregion Fields

        #region Lifecycle

        public Extractor()
        {
            this.ResultPackSize = 1000;
            this.CallTypesToUse =
                CallTypes.Call | CallTypes.Calli | CallTypes.Callvirt | CallTypes.NewObj | CallTypes.LdFld
                | CallTypes.NewArr;
            this.AssemblyPaths = new List<Uri>();
        }

        #endregion Lifecycle

        #region Properties

        /// <summary>
        /// A részeredmények maximális csomagmérete (get, set)
        /// </summary>
        public int ResultPackSize { get; set; }

        /// <summary>
        /// Gets the paths of the assemblies to extract the callgraph from.
        /// </summary>
        public List<Uri> AssemblyPaths { get; private set; }

        /// <summary>
        /// A vizsgálandó hívási típusok (get, set)
        /// </summary>
        public CallTypes CallTypesToUse { get; set; }

        private IServiceProvider pServiceProvider;
        private IServiceProvider ServiceProvider
        {
            get
            {
                if (pServiceProvider == null)
                    pServiceProvider = new ApplicationManager(null);
                return pServiceProvider;
            }
        }

        #endregion Properties

        #region Methods

        private DateTime mExtractTime = new DateTime();
        /// <summary>
        /// Aszinkron megkezdi a hivási gráf kinyerését.
        /// </summary>
        /// <remarks>
        /// A futási állaporól a <see cref="ExtractionProgressChanged"/>, a folyamat befejeztéről
        /// a <see cref="ExtractionDone"/> események tájékoztatnak.
        /// Részeredmények a <see cref="ExtractionSubresultExtracted"/> esemény eseményadatjában
        /// találhatók.
        /// </remarks>
        public void ExtractAsync(IEnumerable<ManualResetEvent> blockers)
        {
            if (this.AssemblyPaths == null)
                throw new InvalidOperationException("AssemblyPaths nincs megadva!");
            if (this.AssemblyPaths.Count == 0)
                throw new InvalidOperationException("Egyetlen asszembli elérési útja sincs megadva!");

            if (mExtractionWorker != null)
            {
                mExtractionWorker.CancelAsync();
                mExtractionWorker.Dispose();
            }
            mExtractionWorker = new BackgroundWorker();
            mExtractionWorker.WorkerSupportsCancellation = true;
            mExtractionWorker.WorkerReportsProgress = true;
            mExtractionWorker.DoWork += new DoWorkEventHandler(mExtractionWorker_DoWork);
            mExtractionWorker.ProgressChanged += new ProgressChangedEventHandler(mExtractionWorker_ProgressChanged);
            mExtractionWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(mExtractionWorker_RunWorkerCompleted);
            mExtractTime = DateTime.Now;
            OnInformating("Hívási gráf kinyerés kezdete:" + mExtractTime.ToString());
            mExtractionWorker.RunWorkerAsync(blockers);
        }

        private DateTime mGetMembersTime = new DateTime();
        public void GetMembersAsync(IEnumerable<ManualResetEvent> blockers)
        {
            if (this.AssemblyPaths == null)
                throw new InvalidOperationException("AssemblyPaths nincs megadva!");
            if (this.AssemblyPaths.Count == 0)
                throw new InvalidOperationException("Egyetlen asszembli elérési útja sincs megadva!");

            if (mGetMembersWorker != null)
            {
                mGetMembersWorker.CancelAsync();
                mGetMembersWorker.Dispose();
            }
            mGetMembersWorker = new BackgroundWorker();
            mGetMembersWorker.WorkerSupportsCancellation = true;
            mGetMembersWorker.WorkerReportsProgress = true;
            mGetMembersWorker.DoWork += new DoWorkEventHandler(mGetMembersWorker_DoWork);
            mGetMembersWorker.ProgressChanged +=
                new ProgressChangedEventHandler(mGetMembersWorker_ProgressChanged);
            mGetMembersWorker.RunWorkerCompleted
                += new RunWorkerCompletedEventHandler(mGetMembersWorker_RunWorkerCompleted);
            mGetMembersTime = DateTime.Now;
            OnInformating("Tagok kinyerésének kezdete:" + mGetMembersTime.ToString());
            mGetMembersWorker.RunWorkerAsync(blockers);
        }

        private DateTime mGetTypesTime = new DateTime();
        public void GetTypesAsync(IEnumerable<ManualResetEvent> blockers)
        {
            if (this.AssemblyPaths == null)
                throw new InvalidOperationException("AssemblyPaths nincs megadva!");
            if (this.AssemblyPaths.Count == 0)
                throw new InvalidOperationException("Egyetlen asszembli elérési útja sincs megadva!");

            if (mGetTypesWorker != null)
            {
                mGetTypesWorker.CancelAsync();
                mGetTypesWorker.Dispose();
            }
            mGetTypesWorker = new BackgroundWorker();
            mGetTypesWorker.WorkerSupportsCancellation = true;
            mGetTypesWorker.WorkerReportsProgress = true;
            mGetTypesWorker.DoWork += new DoWorkEventHandler(mGetTypesWorker_DoWork);
            mGetTypesWorker.ProgressChanged +=
                new ProgressChangedEventHandler(mGetTypesWorker_ProgressChanged);
            mGetTypesWorker.RunWorkerCompleted
                += new RunWorkerCompletedEventHandler(mGetTypesWorker_RunWorkerCompleted);
            mGetTypesTime = DateTime.Now;
            OnInformating("Típusok kinyerésének kezdete:" + mGetTypesTime.ToString());
            mGetTypesWorker.RunWorkerAsync(blockers);
        }

        private DateTime mGetNamespacesTime = new DateTime();
        public void GetNamespacesAsync(IEnumerable<ManualResetEvent> blockers)
        {
            if (this.AssemblyPaths == null)
                throw new InvalidOperationException("AssemblyPaths nincs megadva!");
            if (this.AssemblyPaths.Count == 0)
                throw new InvalidOperationException("Egyetlen asszembli elérési útja sincs megadva!");

            if (mGetNamespacesWorker != null)
            {
                mGetNamespacesWorker.CancelAsync();
                mGetNamespacesWorker.Dispose();
            }
            mGetNamespacesWorker = new BackgroundWorker();
            mGetNamespacesWorker.WorkerSupportsCancellation = true;
            mGetNamespacesWorker.WorkerReportsProgress = true;
            mGetNamespacesWorker.DoWork += new DoWorkEventHandler(mGetNamespacesWorker_DoWork);
            mGetNamespacesWorker.ProgressChanged +=
                new ProgressChangedEventHandler(mGetNamespacesWorker_ProgressChanged);
            mGetNamespacesWorker.RunWorkerCompleted
                += new RunWorkerCompletedEventHandler(mGetNamespacesWorker_RunWorkerCompleted);
            mGetNamespacesTime = DateTime.Now;
            OnInformating("Névterek kinyerésének kezdete:" + mGetNamespacesTime.ToString());
            mGetNamespacesWorker.RunWorkerAsync(blockers);
        }

        private DateTime mGetModulesTime = new DateTime();
        public void GetModulesAsync(IEnumerable<ManualResetEvent> blockers)
        {
            if (this.AssemblyPaths == null)
                throw new InvalidOperationException("AssemblyPaths nincs megadva!");
            if (this.AssemblyPaths.Count == 0)
                throw new InvalidOperationException("Egyetlen asszembli elérési útja sincs megadva!");

            if (mGetModulesWorker != null)
            {
                mGetModulesWorker.CancelAsync();
                mGetModulesWorker.Dispose();
            }
            mGetModulesWorker = new BackgroundWorker();
            mGetModulesWorker.WorkerSupportsCancellation = true;
            mGetModulesWorker.WorkerReportsProgress = true;
            mGetModulesWorker.DoWork += new DoWorkEventHandler(mGetModulesWorker_DoWork);
            mGetModulesWorker.ProgressChanged +=
                new ProgressChangedEventHandler(mGetModulesWorker_ProgressChanged);
            mGetModulesWorker.RunWorkerCompleted
                += new RunWorkerCompletedEventHandler(mGetModulesWorker_RunWorkerCompleted);
            mGetModulesTime = DateTime.Now;
            OnInformating("Modulok kinyerésének kezdete:" + mGetModulesTime.ToString());
            mGetModulesWorker.RunWorkerAsync(blockers);
        }

        private DateTime mGetAssembliesTime = new DateTime();
        public void GetAssembliesAsync(IEnumerable<ManualResetEvent> blockers)
        {
            if (this.AssemblyPaths == null)
                throw new InvalidOperationException("AssemblyPaths nincs megadva!");
            if (this.AssemblyPaths.Count == 0)
                throw new InvalidOperationException("Egyetlen asszembli elérési útja sincs megadva!");

            if (mGetAssembliesWorker != null)
            {
                mGetAssembliesWorker.CancelAsync();
                mGetAssembliesWorker.Dispose();
            }
            mGetAssembliesWorker = new BackgroundWorker();
            mGetAssembliesWorker.WorkerSupportsCancellation = true;
            mGetAssembliesWorker.WorkerReportsProgress = true;
            mGetAssembliesWorker.DoWork += new DoWorkEventHandler(mGetAssembliesWorker_DoWork);
            mGetAssembliesWorker.ProgressChanged +=
                new ProgressChangedEventHandler(mGetAssembliesWorker_ProgressChanged);
            mGetAssembliesWorker.RunWorkerCompleted
                += new RunWorkerCompletedEventHandler(mGetAssembliesWorker_RunWorkerCompleted);
            mGetAssembliesTime = DateTime.Now;
            OnInformating("Asszemblik kinyerésének kezdete:" + mGetAssembliesTime.ToString());
            mGetAssembliesWorker.RunWorkerAsync(blockers);
        }

        private void Help(bool extractCallGraph = false, bool getMembers = false, bool getTypes = false,
            bool getNamespaces = false, bool getModules = false, bool getAssemblies = false)
        {
            HashSet<CallGraphEdgeCollection> callGrahSubresult = null;
            HashSet<ExtendedMemberReference> membersSubresult = null;
            HashSet<ExtendedType> typesSubresult = null;
            HashSet<string> namespacesSubresult = null;
            HashSet<IModule> modulesSubresult = null;
            HashSet<IAssembly> assembliesSubresult = null;

            if (extractCallGraph == true)
                callGrahSubresult = new HashSet<CallGraphEdgeCollection>();//this.ResultPackSize);
            if (getMembers == true)
                membersSubresult = new HashSet<ExtendedMemberReference>();//this.ResultPackSize);
            if (getTypes == true)
                typesSubresult = new HashSet<ExtendedType>();//this.ResultPackSize);
            if (getNamespaces == true)
                namespacesSubresult = new HashSet<string>();//this.ResultPackSize);
            if (getModules == true)
                modulesSubresult = new HashSet<IModule>();//this.ResultPackSize);
            if (getAssemblies == true)
                assembliesSubresult = new HashSet<IAssembly>();

            List<KeyValuePair<IAssemblyManager, IAssembly>> assemblies =
                new List<KeyValuePair<IAssemblyManager, IAssembly>>(this.AssemblyPaths.Count);

            foreach (var path in this.AssemblyPaths)
            {
#if _NET_REFLECTOR
                IAssemblyManager assemblyLoader =
                    (IAssemblyManager)this.ServiceProvider.GetService(typeof(IAssemblyManager));
#elif MONO_CECIL
                Reflector.CodeModel.IAssemblyManager assemblyLoader =
                    new AssemblyLoader();
#endif
                try
                {
                    assemblies.Add(
                        new KeyValuePair<IAssemblyManager, IAssembly>(
                            assemblyLoader,
                            assemblyLoader.LoadFile(path.LocalPath)));
                }
                catch (BadImageFormatException ex)
                {
                    Trace.TraceInformation(ex.Message + " : " + path.LocalPath);
                }
            }

            int assembliesCount, modulesCount, typesCount, membersCount, namespacesCount;
            int assembliesDone = 0, modulesDone = 0, typesDone = 0, membersDone = 0;//, namespacesDone = 0;
            assembliesCount = Count(assemblies, getAssemblies);
            modulesCount = Count(assemblies, countModules: getModules);
            typesCount = Count(assemblies, countTypes: getTypes);
            membersCount = Count(assemblies, countMembers: getMembers);
            namespacesCount = Count(assemblies, countNamespaces: getNamespaces);
            if (getAssemblies == true)
                OnGetAssembliesProgressChanged(-1, 1);
            if (getModules == true)
                OnGetModulesProgressChanged(-1, 1);
            if (getTypes == true)
                OnGetTypesProgressChanged(-1, 1);
            if (getMembers == true)
                OnGetMembersProgressChanged(-1, 1);

            List<IModule> referredModules = null;
            //if (getModules == true || getAssemblies == true || getMembers == true
            //     || getTypes == true || getNamespaces == true)
            referredModules = GetReferredModules(assemblies);

            foreach (var assembly in assemblies)
            {
                if (getAssemblies == true)
                {
                    assembliesSubresult.Add(assembly.Value);
                    OnStateChanged(assembly.Value.Name + " asszembli viszgálata");
                }

                foreach (IModule module in assembly.Value.Modules)
                {
                    if (getModules == true)
                    {
                        OnStateChanged(module.Name + " modul vizsgálata");
                        AddToModulesSubresult(modulesSubresult, module);
                        OnGetModulesProgressChanged(++modulesDone, modulesCount);
                    }
                    foreach (ITypeDeclaration typeDeclaration in module.Types)
                    {
                        if (getTypes == true)
                            OnStateChanged(typeDeclaration.Name + " típus vizsgálata");

                        if (getMembers == true || getNamespaces == true)
                        {
                            GetMembersOrNamespaces(getMembers, getNamespaces,
                                membersSubresult, namespacesSubresult,
                                membersCount, ref membersDone,
                                module, typeDeclaration, outerTypeDeclaration: null);
                        }
                        #region Types and nested types
                        if (getTypes == true)
                        {
                            GetTypes(typesSubresult, ref typesDone, typesCount, module, typeDeclaration,
                                outerTypeDeclaration: null);
                        }
                        #endregion Types and nested types
                        if (getNamespaces == true)
                            AddToNamespacesSubresult(namespacesSubresult, typeDeclaration);

                        // Extract callgraph
                        ForEachCall(extractCallGraph, getMembers, getTypes, getNamespaces, getModules,
                            getAssemblies, callGrahSubresult, membersSubresult, typesSubresult,
                            namespacesSubresult, modulesSubresult, assembliesSubresult, referredModules,
                            module, typeDeclaration);
                    } // each typeDeclaration
                    #region Assembly references
                    if (getAssemblies == true)
                    {
                        foreach (IAssemblyReference assemblyReference in module.AssemblyReferences)
                        {
                            try
                            {
                                AddToAssembliesSubresult(assembliesSubresult, assemblyReference.Resolve());
                            }
                            catch (FileNotFoundException ex)
                            {
                                Trace.TraceWarning("{0} not found!", ex.FileName);
                            }
                            catch (FileLoadException ex)
                            {
                                Trace.TraceWarning("Could not load {0}!", ex.FileName);
                            }
                        }
                    }
                    #endregion Assembly references
                } // each Module

                #region Last subresults
                if (callGrahSubresult != null && callGrahSubresult.Count > 0)
                    OnExtractionSubresultExtracted(new List<CallGraphEdgeCollection>(callGrahSubresult));
                if (extractCallGraph == true)
                    OnExtractionSubresultExtracted(new List<CallGraphEdgeCollection>());
                if (membersSubresult != null && membersSubresult.Count > 0)
                    OnGetMembersSubresultExtracted(new List<ExtendedMemberReference>(membersSubresult));
                if (getMembers == true)
                    OnGetMembersSubresultExtracted(new List<ExtendedMemberReference>());
                if (typesSubresult != null && typesSubresult.Count > 0)
                    OnGetTypesSubresultExtracted(new List<ExtendedType>(typesSubresult));
                if (getTypes == true)
                    OnGetTypesSubresultExtracted(new List<ExtendedType>());
                if (namespacesSubresult != null && namespacesSubresult.Count > 0)
                    OnGetNamespacesSubresultExtracted(new List<string>(namespacesSubresult));
                if (getNamespaces == true)
                    OnGetNamespacesSubresultExtracted(new List<string>());
                if (modulesSubresult != null && modulesSubresult.Count > 0)
                    OnGetModulesSubresultExtracted(new List<IModule>(modulesSubresult));
                if (getModules == true)
                    OnGetModulesSubresultExtracted(new List<IModule>());
                if (assembliesSubresult != null)// && assembliesSubresult.Count > 0)
                    OnGetAssembliesSubresultExtracted(new List<IAssembly>(assembliesSubresult));

                assembly.Key.Unload(assembly.Value);
                if (getAssemblies == true)
                {
                    OnGetAssembliesProgressChanged(++assembliesDone, assembliesCount);
                    OnGetAssembliesSubresultExtracted(new List<IAssembly>());
                }
                #endregion Last subresults
            } // each Assembly
            if (getAssemblies == true)
                OnGetAssembliesDone(new RunWorkerCompletedEventArgs(null, null, false));
        }

        private void GetMembersOrNamespaces(bool getMembers, bool getNamespaces,
            HashSet<ExtendedMemberReference> membersSubresult, HashSet<string> namespacesSubresult,
            int membersCount, ref int membersDone,
            IModule module, ITypeDeclaration typeDeclaration, ITypeDeclaration outerTypeDeclaration)
        {
            ForEachMember(membersSubresult, namespacesSubresult, module, typeDeclaration,
                ref membersDone, membersCount, getMembers, getNamespaces,
                outerTypeDeclaration: outerTypeDeclaration);
            foreach (ITypeDeclaration nested in typeDeclaration.NestedTypes)
            {
                GetMembersOrNamespaces(getMembers, getNamespaces, membersSubresult, namespacesSubresult,
                    membersCount, ref membersDone, module, nested, typeDeclaration);
            }
        }

        private void GetTypes(HashSet<ExtendedType> typesSubresult, ref int typesDone, int typesCount,
            IModule containerModule,
            ITypeDeclaration typeDeclaration, ITypeDeclaration outerTypeDeclaration)
        {

            AddToTypesSubresult(typesSubresult, containerModule, typeDeclaration, outerTypeDeclaration);
            foreach (ITypeDeclaration nested in typeDeclaration.NestedTypes)
            {
                GetTypes(typesSubresult, ref typesDone, typesCount, containerModule,
                typeDeclaration: nested, outerTypeDeclaration: typeDeclaration);
            }
            OnGetTypesProgressChanged(++typesDone, typesCount);
        }

        private int Count(List<KeyValuePair<IAssemblyManager, IAssembly>> assemblies,
            bool countAssemblies = false, bool countModules = false, bool countTypes = false,
            bool countMembers = false, bool countNamespaces = false)
        {
            HashSet<string> namespaces = null;
            if (countNamespaces == true)
                namespaces = new HashSet<string>();
            int count = 0;
            foreach (var assembly in assemblies)
            {
                foreach (IModule module in assembly.Value.Modules)
                {
                    foreach (ITypeDeclaration typeDeclaration in module.Types)
                    {
                        if (countMembers == true)
                        {
                            foreach (var eventDeclaration in typeDeclaration.Events)
                                count++;
                            foreach (var fieldDeclaration in typeDeclaration.Fields)
                                count++;
                            foreach (var methodDeclaration in typeDeclaration.Methods)
                                count++;
                            foreach (var propertyDeclaration in typeDeclaration.Properties)
                                count++;
                        }
                        if (countTypes == true)
                            count++;
                        if (countNamespaces == true
                            && namespaces.Contains(typeDeclaration.Namespace) == false)
                            namespaces.Add(typeDeclaration.Namespace);
                        foreach (ITypeDeclaration nested in typeDeclaration.NestedTypes)
                        {
                            if (countMembers == true)
                            {
                                foreach (var eventDeclaration in typeDeclaration.Events)
                                    count++;
                                foreach (var fieldDeclaration in typeDeclaration.Fields)
                                    count++;
                                foreach (var methodDeclaration in typeDeclaration.Methods)
                                    count++;
                                foreach (var propertyDeclaration in typeDeclaration.Properties)
                                    count++;
                            }
                            if (countTypes == true)
                                count++;
                        }
                    }
                    if (countModules == true)
                        count++;
                }
                if (countAssemblies == true)
                    count++;
            }
            if (countNamespaces == true)
                count += namespaces.Count;
            return count;
        }

        private void ForEachCall(bool extractCallGraph, bool getMembers, bool getTypes, bool getNamespaces,
            bool getModules, bool getAssemblies, HashSet<CallGraphEdgeCollection> callGrahSubresult,
            HashSet<ExtendedMemberReference> membersSubresult, HashSet<ExtendedType> typesSubresult,
            HashSet<string> namespacesSubresult, HashSet<IModule> modulesSubresult,
            HashSet<IAssembly> assembliesSubresult, List<IModule> referredModules, IModule module,
            ITypeDeclaration outerTypeDeclaration)
        {
            if (getNamespaces == true)
                OnStateChanged(outerTypeDeclaration.Name + " típus vizsgálata névterek kinyeréséért");
            foreach (IMethodDeclaration methodDeclaration in outerTypeDeclaration.Methods)
            {
                ExtendedMemberReference caller =
                    new ExtendedMemberReference(module, methodDeclaration, outerTypeDeclaration);
                IMethodBody methodBody = methodDeclaration.Body as IMethodBody;
                if (methodBody != null)
                {
                    List<CallGraphEdge> called = null;
                    if (extractCallGraph == true)
                        called = new List<CallGraphEdge>();
                    foreach (IInstruction instruction in methodBody.Instructions)
                    {
                        IMemberReference mr = null;
                        try
                        {
                            mr = instruction.Value as IMemberReference;
                        }
                        catch (Mono.Cecil.AssemblyResolutionException ex)
                        {
                            Trace.TraceInformation(
                                "Could not resolve instruction due to an assembly resolution exeption: {0}",
                                ex.Message);
                        }
                        catch (NotSupportedException ex)
                        {
                            Trace.TraceInformation(ex.Message);
                        }
                        //if (getModules == true || getAssemblies == true || getMembers == true
                        //     || getTypes == true || getNamespaces == true)
                        if (mr != null)
                        {
                            IModule containerModule = GetContainerModule(mr, module, referredModules);
                            if (getNamespaces == true)
                            {
                                ITypeDeclaration td = null;
                                IArrayType at = null;
                                if (mr.DeclaringType.TryGetTypeDeclaration(out td) == true)
                                    AddToNamespacesSubresult(namespacesSubresult, td);
                                else if (mr.DeclaringType.TryGetArrayType(out at) == true)
                                    ;//AddToNamespacesSubresult(namespacesSubresult, at);
                            }
                            if (getAssemblies == true && containerModule != null)
                                AddToAssembliesSubresult(assembliesSubresult, containerModule.Assembly);
                            if (getModules == true && containerModule != null)
                                AddToModulesSubresult(modulesSubresult, containerModule);
                            if (getTypes == true)
                            {
                                ITypeDeclaration td = null;
                                IArrayType at = null;
                                if (mr.DeclaringType.TryGetTypeDeclaration(out td))
                                    AddToTypesSubresult(typesSubresult, containerModule, td);
                                else if (mr.DeclaringType.TryGetArrayType(out at))
                                    AddToTypesSubresult(typesSubresult, containerModule, at);
                            }
                            if (getMembers == true)
                                AddToMembersSubresult(membersSubresult, containerModule, mr, outerTypeDeclaration);
                            if (extractCallGraph == true)
                            {
                                CallTypes callType = CallTypesExtension.Parse(instruction.Code);
                                if ((this.CallTypesToUse & callType) == callType
                                    && callType != CallTypes.None)
                                {
                                    called.Add(
                                        new CallGraphEdge(
                                            new ExtendedMemberReference(containerModule, mr, outerTypeDeclaration),
                                            callType));
                                    //Console.WriteLine("  Calls to: " +
                                    //        instruction.Value.ToString());
                                }
                            }
                        }
                    }	// each instruction

                    if (extractCallGraph == true)
                    {
                        AddToCallGraphSubresult(callGrahSubresult, caller, called);
                    }
                }

            } // each methodDeclaration
        }

        #region Add to subresult

        private void AddToCallGraphSubresult(HashSet<CallGraphEdgeCollection> callGrahSubresult,
            ExtendedMemberReference caller, List<CallGraphEdge> called)
        {
#if DEBUG
            foreach (var item in called)
            {
                ITypeDeclaration td;
                if (item.ExtendedMemberReference.MemberReference.DeclaringType.TryGetTypeDeclaration(out td))
                {
                    if (td.Name.Contains("Object"))
                        ;
                }
            }
#endif
            CallGraphEdgeCollection cgec = new CallGraphEdgeCollection(caller, called);
            if (callGrahSubresult.Contains(cgec) == false)
                callGrahSubresult.Add(cgec);
            if (callGrahSubresult.Count >= this.ResultPackSize)
            {
                OnExtractionSubresultExtracted(new List<CallGraphEdgeCollection>(callGrahSubresult));
                callGrahSubresult.Clear();
            }
        }

        private void AddToTypesSubresult(HashSet<ExtendedType> typesSubresult, IModule module,
            IType type, IType outerType = null)
        {
            if (module == null)//case of assembly not found
                return;
            ExtendedType et = new ExtendedType(module, type, outerType);
#if DEBUG
            ITypeDeclaration td = null;
            et.Type.TryGetTypeDeclaration(out td);
            int i;
#endif //DEBUG
            if (et.IsValid == true)
            {
                if (typesSubresult.Contains(et) && et.OuterType != null)
                    typesSubresult.Remove(et);
                if (typesSubresult.Contains(et) == false)
                    typesSubresult.Add(et);
                if (typesSubresult.Count >= this.ResultPackSize)
                {
                    OnGetTypesSubresultExtracted(new List<ExtendedType>(typesSubresult));
                    typesSubresult.Clear();
                }
            }
        }

        private void AddToNamespacesSubresult(HashSet<string> namespacesSubresult,
            ITypeDeclaration typeDeclaration)
        {
            if (namespacesSubresult.Contains(typeDeclaration.Namespace) == false)
                namespacesSubresult.Add(typeDeclaration.Namespace);
            if (namespacesSubresult.Count >= this.ResultPackSize)
            {
                OnGetNamespacesSubresultExtracted(new List<string>(namespacesSubresult));
                namespacesSubresult.Clear();
            }
        }

        private void AddToAssembliesSubresult(HashSet<IAssembly> assembliesSubresult,
            IAssembly assembly)
        {
            if (assembliesSubresult.Contains(assembly) == false)
                assembliesSubresult.Add(assembly);
            if (assembliesSubresult.Count >= this.ResultPackSize)
            {
                OnGetAssembliesSubresultExtracted(
                    new List<IAssembly>(assembliesSubresult));
                assembliesSubresult.Clear();
            }
        }

        private void AddToModulesSubresult(HashSet<IModule> modulesSubresult, IModule module)
        {
            if (modulesSubresult.Contains(module) == false)
                modulesSubresult.Add(module);
            if (modulesSubresult.Count >= this.ResultPackSize)
            {
                OnGetModulesSubresultExtracted(new List<IModule>(modulesSubresult));
                modulesSubresult.Clear();
            }
        }

        private void AddToMembersSubresult(HashSet<ExtendedMemberReference> subresult, IModule module,
            IMemberReference memberReference, ITypeDeclaration outerTypeDeclaration)
        {
            if (module == null)// case of assembly not found
                return;
            ExtendedMemberReference emr =
                new ExtendedMemberReference(module, memberReference, outerTypeDeclaration);
#if DEBUG
            ITypeDeclaration td;
            if (memberReference.DeclaringType.TryGetTypeDeclaration(out td) == true)
            {
                bool l = false;
                foreach (ITypeDeclaration type in module.Types)
                {
                    if (type.CompareTo(td) == 0)
                    {
                        l = true;
                        break;
                    }
                    foreach (ITypeDeclaration nestedType in type.NestedTypes)
                    {
                        if (nestedType.CompareTo(td) == 0)
                        {
                            l = true;
                            break;
                        }
                    }
                }
                if (l == false)
                    ;
            }
#endif //DEBUG
            if (subresult.Contains(emr) == false)
                subresult.Add(emr);
            if (subresult.Count >= this.ResultPackSize)
            {
                OnGetMembersSubresultExtracted(new List<ExtendedMemberReference>(subresult));
                subresult.Clear();
            }
        }

        #endregion Add to subresult

        private List<IModule> GetReferredModules(List<KeyValuePair<IAssemblyManager, IAssembly>> assemblies)
        {
            HashSet<IModule> referredModules = new HashSet<IModule>();

            foreach (var assembly in GetReferredAssemblies(assemblies))
            {
                foreach (IModule module in assembly.Modules)
                {
                    if (referredModules.Contains(module) == false)
                        referredModules.Add(module);
                }
            }
            return new List<IModule>(referredModules);
        }

        private List<IAssembly> GetReferredAssemblies(List<KeyValuePair<IAssemblyManager, IAssembly>> assemblies)
        {
            HashSet<IAssembly> referredAssemblies = new HashSet<IAssembly>();
            HashSet<IAssembly> ownAssemblies = new HashSet<IAssembly>();
            foreach (var item in assemblies)
            {
                ownAssemblies.Add(item.Value);
            }
            foreach (var item in assemblies)
            {
                foreach (IModule module in item.Value.Modules)
                {
                    foreach (IAssemblyReference assemblyReference in module.AssemblyReferences)
                    {
                        IAssembly referredAssembly = null;
                        try
                        {
                            referredAssembly = assemblyReference.Resolve();
                        }
                        catch (FileNotFoundException ex)
                        {
                            var query = ownAssemblies.Where(a => a.Name == assemblyReference.Name);
                            if (query.Count() > 0)
                                referredAssembly = query.First();
                            else
                                //throw ex;
                                //OnInformating(ex.Message);
                                Trace.TraceWarning("{0} not found at GetReferredAssemblies(..)", ex.FileName);
                        }
                        catch (FileLoadException ex)
                        {
                            var query = ownAssemblies.Where(a => a.Name == assemblyReference.Name);
                            if (query.Count() > 0)
                                referredAssembly = query.First();
                            else
                                Trace.TraceWarning("Could not load {0} at GetReferredAssemblies(..)", ex.FileName);
                        }
                        if (referredAssembly != null
                            && ownAssemblies.Contains(referredAssembly) == false
                            && referredAssemblies.Contains(referredAssembly) == false)
                            referredAssemblies.Add(referredAssembly);
                    }
                }
            }
            referredAssemblies.UnionWith(ownAssemblies);
            return new List<IAssembly>(referredAssemblies);
        }

        private IModule GetContainerModule(IMemberReference mr, IModule module, List<IModule> referredModules)
        {
            ITypeDeclaration declaringType = null;
            List<IModule> modules = new List<IModule>();
            modules.Add(module);
            var concatenatedModules = modules.Concat(referredModules);
            if (mr.DeclaringType.TryGetTypeDeclaration(out declaringType))
            {
                foreach (var currentModule in concatenatedModules)
                {
                    foreach (ITypeDeclaration type in currentModule.Types)
                    {
                        if (GetContainerModule(declaringType, type) == true)
                            return currentModule;
                    }
                }
            }
            //Trace.TraceInformation(
            //    "Can not find module where " + mr.Name + " member of "
            //    + (declaringType != null ? declaringType.Name : "unresolved type") + " is declared.");
            return null;
        }

        private static bool GetContainerModule(ITypeDeclaration declaringType, ITypeDeclaration type)
        {
            if (type.CompareTo(declaringType) == 0)
                return true;
            foreach (ITypeDeclaration nested in type.NestedTypes)
            {
                if (GetContainerModule(declaringType, nested) == true)
                    return true;
            }
            return false;
        }

        private void HelpExtract()
        {
            Help(extractCallGraph: true);
        }

        private void HelpGetMembers()
        {
            Help(getMembers: true);
        }

        private void ForEachMember(HashSet<ExtendedMemberReference> subresult, HashSet<string> namespaceSubresult,
            IModule module, ITypeDeclaration typeDeclaration,
            ref int membersDone, int membersCount,
            bool getMembers, bool getNamespaces,
            ITypeDeclaration outerTypeDeclaration)
        {
            if (getNamespaces == true)
                OnStateChanged(typeDeclaration.Name + " típus vizsgálata névterek kinyeréséért");
            //TODO review: a methodDecl paramétereinek típusain kívül kell-e nézni a névtereket
            if (getMembers == true)
            {
                foreach (var eventDeclaration in typeDeclaration.Events)
                {
                    AddToMembersSubresult(subresult, module, eventDeclaration as IMemberReference,
                        outerTypeDeclaration);
                    OnGetMembersProgressChanged(++membersDone, membersCount);
                }
                foreach (var fieldDeclaration in typeDeclaration.Fields)
                {
                    AddToMembersSubresult(subresult, module, fieldDeclaration as IMemberReference,
                        outerTypeDeclaration);
                    OnGetMembersProgressChanged(++membersDone, membersCount);
                }
            }
            foreach (IMethodDeclaration methodDeclaration in typeDeclaration.Methods)
            {
                if (getMembers == true)
                {
                    AddToMembersSubresult(subresult, module, methodDeclaration as IMemberReference,
                        outerTypeDeclaration);
                    OnGetMembersProgressChanged(++membersDone, membersCount);
                }
                if (getNamespaces == true)
                    foreach (IParameterDeclaration parameterDeclaration in methodDeclaration.Parameters)
                    {
                        ITypeDeclaration td = null;
                        try
                        {
                            if (parameterDeclaration.ParameterType.TryGetTypeDeclaration(out td))
                            {
                                string ns = td.Namespace;
                                if (namespaceSubresult.Contains(ns) == false)
                                    namespaceSubresult.Add(ns);
                            }
                            else
                            {
                                //Debugger.Break();
#if EXTR_DEBUG
                            Debug.WriteLine("Unresolved parameter declaration: "
                                + parameterDeclaration.ParameterType.ToString());
#endif
                            }
                        }
                        catch (Mono.Cecil.AssemblyResolutionException ex)
                        {
                            Trace.TraceWarning("Not all the params of " + methodDeclaration.Name + " has been resolved. " + ex.Message);
                        }
                    }
            }
            if (getMembers == true)
                foreach (var propertyDeclaration in typeDeclaration.Properties)
                {
                    AddToMembersSubresult(subresult, module, propertyDeclaration as IMemberReference,
                        outerTypeDeclaration);
                    OnGetMembersProgressChanged(++membersDone, membersCount);
                }
        }

        private void HelpGetTypes()
        {
            Help(getTypes: true);
        }

        private void HelpGetNamespaces()
        {
            Help(getNamespaces: true);
        }

        private void HelpGetModules()
        {
            Help(getModules: true);
        }

        private void HelpGetAssemblies()
        {
            Help(getAssemblies: true);
        }

        #endregion Methods

        #region Events

        #region Extraction

        public event EventHandler<RunWorkerCompletedEventArgs> ExtractionDone;
        protected virtual void OnExtractionDone(RunWorkerCompletedEventArgs e)
        {
            //mOnExtractionDoneBlocker.WaitOne();
            if (this.ExtractionDone != null)
                this.ExtractionDone(this, e);
        }

        public event EventHandler<ProgressChangedEventArgs> ExtractionProgressChanged;
        protected virtual void OnExtractionProgressChanged(ProgressChangedEventArgs e)
        {
            if (this.ExtractionProgressChanged != null)
                this.ExtractionProgressChanged(this, e);
        }

        protected void OnExtractionProgressChanged(int done, int max)
        {
            OnExtractionProgressChanged(
                new ProgressChangedEventArgs(
                    (int)(((double)done / (double)max) * 100.0), null));
        }

        /// <summary>
        /// Event occures when a subresult of call graph is extracted.
        /// </summary>
        /// <remarks>
        /// Empty list in event data signs that no more subresults will be extracted.
        /// </remarks>
        public event EventHandler<SubresultEventArgs<CallGraphEdgeCollection>> ExtractionSubresultExtracted;
        protected virtual void OnExtractionSubresultExtracted(List<CallGraphEdgeCollection> subresult)
        {
            OnExtractionSubresultExtracted(new SubresultEventArgs<CallGraphEdgeCollection>(subresult));
        }

        protected virtual void OnExtractionSubresultExtracted(SubresultEventArgs<CallGraphEdgeCollection> e)
        {
            if (this.ExtractionSubresultExtracted != null)
                this.ExtractionSubresultExtracted(this, e);
            //mOnExtractionDoneBlocker.Set();
        }

        #endregion Extraction

        #region GetMembers

        public event EventHandler<RunWorkerCompletedEventArgs> GetMembersDone;
        protected virtual void OnGetMembersDone(RunWorkerCompletedEventArgs e)
        {
            //mOnGetMembersDoneBlocker.WaitOne();
            if (this.GetMembersDone != null)
                this.GetMembersDone(this, e);
        }

        public event EventHandler<ProgressChangedEventArgs> GetMembersProgressChanged;
        protected virtual void OnGetMembersProgressChanged(ProgressChangedEventArgs e)
        {
            if (this.GetMembersProgressChanged != null)
                this.GetMembersProgressChanged(this, e);
        }

        protected void OnGetMembersProgressChanged(int done, int max)
        {
            OnGetMembersProgressChanged(
                new ProgressChangedEventArgs(
                    (int)(((double)done / (double)max) * 100.0), null));
        }

        /// <summary>
        /// Event occures when a subresult of member nodes is extracted.
        /// </summary>
        /// <remarks>
        /// Empty list in event data signs that no more subresults will be extracted.
        /// </remarks>
        public event EventHandler<SubresultEventArgs<ExtendedMemberReference>> GetMembersSubresultExtracted;
        protected virtual void OnGetMembersSubresultExtracted(List<ExtendedMemberReference> subresult)
        {
            OnGetMembersSubresultExtracted(new SubresultEventArgs<ExtendedMemberReference>(subresult));
        }

        protected virtual void OnGetMembersSubresultExtracted(SubresultEventArgs<ExtendedMemberReference> e)
        {
            if (this.GetMembersSubresultExtracted != null)
                this.GetMembersSubresultExtracted(this, e);
            //mOnGetMembersDoneBlocker.Set();
        }

        #endregion GetMembers

        #region GetTypes

        public event EventHandler<RunWorkerCompletedEventArgs> GetTypesDone;
        protected virtual void OnGetTypesDone(RunWorkerCompletedEventArgs e)
        {
            //mOnGetTypesDoneBlocker.WaitOne();
            if (this.GetTypesDone != null)
                this.GetTypesDone(this, e);
        }

        public event EventHandler<ProgressChangedEventArgs> GetTypesProgressChanged;
        protected virtual void OnGetTypesProgressChanged(ProgressChangedEventArgs e)
        {
            if (this.GetTypesProgressChanged != null)
                this.GetTypesProgressChanged(this, e);
        }

        protected void OnGetTypesProgressChanged(int done, int max)
        {
            OnGetTypesProgressChanged(
                new ProgressChangedEventArgs(
                    (int)(((double)done / (double)max) * 100.0), null));
        }

        /// <summary>
        /// Event occures when a subresult type nodes is extracted.
        /// </summary>
        /// <remarks>
        /// Empty list in event data signs that no more subresults will be extracted.
        /// </remarks>
        public event EventHandler<SubresultEventArgs<ExtendedType>> GetTypesSubresultExtracted;
        protected virtual void OnGetTypesSubresultExtracted(List<ExtendedType> subresult)
        {
            OnGetTypesSubresultExtracted(new SubresultEventArgs<ExtendedType>(subresult));
        }

        protected virtual void OnGetTypesSubresultExtracted(SubresultEventArgs<ExtendedType> e)
        {
            if (this.GetTypesSubresultExtracted != null)
                this.GetTypesSubresultExtracted(this, e);
            //mOnGetTypesDoneBlocker.Set();
        }

        #endregion GetTypes

        #region GetNamespaces

        public event EventHandler<RunWorkerCompletedEventArgs> GetNamespacesDone;
        protected virtual void OnGetNamespacesDone(RunWorkerCompletedEventArgs e)
        {
            //mOnGetNamespacesDoneBlocker.WaitOne();
            if (this.GetNamespacesDone != null)
                this.GetNamespacesDone(this, e);
        }

        public event EventHandler<ProgressChangedEventArgs> GetNamespacesProgressChanged;
        protected virtual void OnGetNamespacesProgressChanged(ProgressChangedEventArgs e)
        {
            if (this.GetNamespacesProgressChanged != null)
                this.GetNamespacesProgressChanged(this, e);
        }

        protected void OnGetNamespacesProgressChanged(int done, int max)
        {
            OnGetNamespacesProgressChanged(
                new ProgressChangedEventArgs(
                    (int)(((double)done / (double)max) * 100.0), null));
        }

        /// <summary>
        /// Event occures when a subresult namespace nodes is extracted.
        /// </summary>
        /// <remarks>
        /// Empty list in event data signs that no more subresults will be extracted.
        /// </remarks>
        public event EventHandler<SubresultEventArgs<string>> GetNamespacesSubresultExtracted;
        protected virtual void OnGetNamespacesSubresultExtracted(List<string> subresult)
        {
            OnGetNamespacesSubresultExtracted(new SubresultEventArgs<string>(subresult));
        }

        protected virtual void OnGetNamespacesSubresultExtracted(SubresultEventArgs<string> e)
        {
            if (this.GetNamespacesSubresultExtracted != null)
                this.GetNamespacesSubresultExtracted(this, e);
            //mOnGetNamespacesDoneBlocker.Set();
        }

        #endregion GetNamespaces

        #region GetModules

        public event EventHandler<RunWorkerCompletedEventArgs> GetModulesDone;
        protected virtual void OnGetModulesDone(RunWorkerCompletedEventArgs e)
        {
            //mOnGetModulesDoneBlocker.WaitOne();
            if (this.GetModulesDone != null)
                this.GetModulesDone(this, e);
        }

        public event EventHandler<ProgressChangedEventArgs> GetModulesProgressChanged;
        protected virtual void OnGetModulesProgressChanged(ProgressChangedEventArgs e)
        {
            if (this.GetModulesProgressChanged != null)
                this.GetModulesProgressChanged(this, e);
        }

        protected void OnGetModulesProgressChanged(int done, int max)
        {
            OnGetModulesProgressChanged(
                new ProgressChangedEventArgs(
                    (int)(((double)done / (double)max) * 100.0), null));
        }

        /// <summary>
        /// Event occures when a subresult module nodes is extracted.
        /// </summary>
        /// <remarks>
        /// Empty list in event data signs that no more subresults will be extracted.
        /// </remarks>
        public event EventHandler<SubresultEventArgs<IModule>> GetModulesSubresultExtracted;
        protected virtual void OnGetModulesSubresultExtracted(List<IModule> subresult)
        {
            OnGetModulesSubresultExtracted(new SubresultEventArgs<IModule>(subresult));
        }

        protected virtual void OnGetModulesSubresultExtracted(SubresultEventArgs<IModule> e)
        {
            if (this.GetModulesSubresultExtracted != null)
                this.GetModulesSubresultExtracted(this, e);
            //mOnGetModulesDoneBlocker.Set();
        }

        #endregion GetModules

        #region GetAssemblies

        public event EventHandler<RunWorkerCompletedEventArgs> GetAssembliesDone;
        protected virtual void OnGetAssembliesDone(RunWorkerCompletedEventArgs e)
        {
            //mOnGetAssembliesDoneBlocker.WaitOne();
            if (this.GetAssembliesDone != null)
                this.GetAssembliesDone(this, e);
        }

        public event EventHandler<ProgressChangedEventArgs> GetAssembliesProgressChanged;
        protected virtual void OnGetAssembliesProgressChanged(ProgressChangedEventArgs e)
        {
            if (this.GetAssembliesProgressChanged != null)
                this.GetAssembliesProgressChanged(this, e);
        }

        protected void OnGetAssembliesProgressChanged(int done, int max)
        {
            OnGetAssembliesProgressChanged(
                new ProgressChangedEventArgs(
                    (int)(
                    ((double)done / (double)max) * 100.0), null));
        }

        /// <summary>
        /// Event occures when a subresult assembly nodes is extracted.
        /// </summary>
        /// <remarks>
        /// Empty list in event data signs that no more subresults will be extracted.
        /// </remarks>
        public event EventHandler<SubresultEventArgs<IAssembly>> GetAssembliesSubresultExtracted;
        protected virtual void OnGetAssembliesSubresultExtracted(List<IAssembly> subresult)
        {
            OnGetAssembliesSubresultExtracted(new SubresultEventArgs<IAssembly>(subresult));
        }

        protected virtual void OnGetAssembliesSubresultExtracted(SubresultEventArgs<IAssembly> e)
        {
            if (this.GetAssembliesSubresultExtracted != null)
                this.GetAssembliesSubresultExtracted(this, e);
            //mOnGetAssembliesDoneBlocker.Set();
        }

        #endregion GetAssemblies

        #region Information

        public event EventHandler<InformationEventArgs> Informating;
        protected virtual void OnInformating(InformationEventArgs e)
        {
            if (this.Informating != null)
                this.Informating(this, e);
        }

        protected void OnInformating(string information)
        {
            OnInformating(new InformationEventArgs(information));
        }

        #endregion Information

        #region StateChange

        public event EventHandler<InformationEventArgs> StateChanged;
        protected virtual void OnStateChanged(InformationEventArgs e)
        {
            if (this.StateChanged != null)
                this.StateChanged(this, e);
        }

        protected void OnStateChanged(string state)
        {
            OnStateChanged(new InformationEventArgs(state));
        }

        #endregion StateChange

        #endregion Events

        #region EventHandlers

        #region mExtractionWorker

        void mExtractionWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (var blocker in e.Argument as IEnumerable<ManualResetEvent>)
            {
                blocker.WaitOne();
            }

            HelpExtract();
            TimeSpan ts = DateTime.Now.Subtract(mExtractTime);
            OnInformating("Hívások kinyerése kész:" + DateTime.Now.ToString());
            Debug.WriteLine("[Time] Extract done after " + ts.ToString());
            OnInformating("Hívások kinyerése kész " + ts.ToString() + " idő alatt");
        }

        void mExtractionWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnExtractionProgressChanged(e);
        }

        void mExtractionWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnExtractionDone(e);
        }

        #endregion mExtractionWorker

        #region mGetMembersWorker

        void mGetMembersWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (var blocker in e.Argument as IEnumerable<ManualResetEvent>)
            {
                blocker.WaitOne();
            }

            HelpGetMembers();
            TimeSpan ts = DateTime.Now.Subtract(mGetMembersTime);
            OnInformating("Tagok kinyerése kész:" + DateTime.Now.ToString());
            Debug.WriteLine("[Time] GetMembers done after " + ts.ToString());
            OnInformating("Tagok kinyerése kész " + ts.ToString() + " idő alatt");
        }

        void mGetMembersWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnGetMembersProgressChanged(e);
        }

        void mGetMembersWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnGetMembersDone(e);
        }

        #endregion mGetMembersWorker

        #region mGetTypesWorker

        void mGetTypesWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (var blocker in e.Argument as IEnumerable<ManualResetEvent>)
            {
                blocker.WaitOne();
            }

            HelpGetTypes();
            TimeSpan ts = DateTime.Now.Subtract(mGetTypesTime);
            OnInformating("Típusok kinyerése kész:" + DateTime.Now.ToString());
            Debug.WriteLine("[Time] GetTypes done after " + ts.ToString());
            OnInformating("Típusok kinyerése kész " + ts.ToString() + " idő alatt");
        }

        void mGetTypesWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnGetTypesProgressChanged(e);
        }

        void mGetTypesWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnGetTypesDone(e);
        }

        #endregion mGetTypesWorker

        #region mGetNamespacesWorker

        void mGetNamespacesWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (var blocker in e.Argument as IEnumerable<ManualResetEvent>)
            {
                blocker.WaitOne();
            }

            HelpGetNamespaces();
            TimeSpan ts = DateTime.Now.Subtract(mGetNamespacesTime);
            OnInformating("Névterek kinyerése kész:" + DateTime.Now.ToString());
            Debug.WriteLine("[Time] GetNamespaces done after " + ts.ToString());
            OnInformating("Névterek kinyerése kész " + ts.ToString() + " idő alatt");
        }

        void mGetNamespacesWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnGetNamespacesProgressChanged(e);
        }

        void mGetNamespacesWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnGetNamespacesDone(e);
        }

        #endregion mGetNamespacesWorker

        #region mGetModulesWorker

        void mGetModulesWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (var blocker in e.Argument as IEnumerable<ManualResetEvent>)
            {
                blocker.WaitOne();
            }

            HelpGetModules();
            TimeSpan ts = DateTime.Now.Subtract(mGetModulesTime);
            OnInformating("Modulok kinyerése kész:" + DateTime.Now.ToString());
            Debug.WriteLine("[Time] GetModules done after " + ts.ToString());
            OnInformating("Modulok kinyerése kész " + ts.ToString() + " idő alatt");
        }

        void mGetModulesWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnGetModulesProgressChanged(e);
        }

        void mGetModulesWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnGetModulesDone(e);
        }

        #endregion mGetModulesWorker

        #region mGetAssembliesWorker

        void mGetAssembliesWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (var blocker in e.Argument as IEnumerable<ManualResetEvent>)
            {
                blocker.WaitOne();
            }

            HelpGetAssemblies();
            TimeSpan ts = DateTime.Now.Subtract(mGetAssembliesTime);
            OnInformating("Asszemblik kinyerése kész:" + DateTime.Now.ToString());
            Debug.WriteLine("[Time] GetAssemblies done after " + ts.ToString());
            OnInformating("Asszemblik kinyerése kész " + ts.ToString() + " idő alatt");
        }

        void mGetAssembliesWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnGetAssembliesProgressChanged(e);
        }

        void mGetAssembliesWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //OnGetAssembliesDone(e);
        }

        #endregion mGetAssembliesWorker

        #endregion EventHandlers
    }
}
